package controller;

import java.io.BufferedInputStream;
import java.io.IOException;

import model.Direction;
import model.GameEvent;
import model.GameListenerAdapter;
import model.GameModel;

/**
 * The ConsoleControl class provides a simple text based interface
 * for the game of turn based pacman.
 * 
 * @author Robert Gillespie (Implementation)
 * @author Alexander Craig (Skeleton)
 * @version 0.1
 */
public class ConsoleControl extends GameListenerAdapter {
	
	/**Bad input message.*/
	private static final String MSG_BAD_INPUT = "Invalid input, please try again.";
	/**Thank you for playing message.*/
	private static final String MSG_THANK_YOU = "Thank you for playing!";
	/**Play again message.*/
	private static final String MSG_PLAY_AGAIN = "Would you like to play again? [Y]es / [N]o";
	
	/** the keys used to play the game */
	private static final char YES_KEY = 'y';
	private static final char NO_KEY = 'n';
	private static final char QUIT_KEY = 'q';
	private static final char RIGHT_KEY = 'd';
	private static final char DOWN_KEY = 's';
	private static final char LEFT_KEY = 'a';
	private static final char UP_KEY = 'w';
	
	/** The game model */
	private GameModel model;
	/** Buffered input for reading in characters*/
	private BufferedInputStream bi;
	/**Game State*/
	private boolean continueGame;
	
	/**
	 * Creates a Console Controller for use in the tb-pacman game
	 * @param model the model for the pacman game
	 */
	public ConsoleControl(GameModel model){
		model.addGameListener(this);//Allows the controller to get game events
		this.model = model;
		bi = new BufferedInputStream(System.in);
		continueGame = true;
	}
	
	/**
	 * Simple execution method.
	 * If w,a,s or d are pressed pacman will move in it's respective direction.
	 * If q is pressed the game will end.
	 * @return True if the game is to continue to execute. False if game is complete.
	 */
	private boolean execute() {
		try {
			char c = (char) bi.read();
			switch(c){
				case UP_KEY: model.makeMove(Direction.NORTH); break;
				case LEFT_KEY: model.makeMove(Direction.WEST); break;
				case DOWN_KEY: model.makeMove(Direction.SOUTH); break;
				case RIGHT_KEY: model.makeMove(Direction.EAST); break;
				case QUIT_KEY: gameOver(null);
				default: break;
			}
		} catch (IOException e) {
			System.err.println(e.getStackTrace());
		}
		
		return continueGame;
	}
	
	public void run() {
		if (continueGame) {
			while(this.execute());
		}
	}

	/**
	 * Should a gameOver Event be broadcast, the controller will end the game.
	 */
	@Override
	public void gameOver(GameEvent event) {
		continueGame = false;
		System.out.println(MSG_PLAY_AGAIN);
		boolean valid = false;
		while(!valid) {
			try {
				bi = new BufferedInputStream(System.in);
				char c = (char) bi.read();
				if (c == Character.toUpperCase(NO_KEY) || c == NO_KEY) {
					System.out.println(MSG_THANK_YOU);
					valid = true;
				} else if (c == YES_KEY || c == Character.toUpperCase(YES_KEY)) {
					model.resetGame();
					continueGame = true;
					valid = true;
				} else {
					throw new IOException();
				}
			} catch (IOException e) {
				System.out.println(MSG_BAD_INPUT);
			}
		}
	}
	
	/**
	 * Prompts the player to start a new game when they beat the level.
	 * In the full game, this should probably load the next level.
	 * 
	 */
	@Override
	public void levelComplete(GameEvent e) {
		gameOver(e);
	}
}